/*
 *   Copyright 2012-present OSBI Ltd
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 */

// Packages
import React, { Component, Fragment } from 'react';
import browserInfo from 'browser-info';
import newGitlabIssueUrl from 'new-gitlab-issue-url';
import {
  Button,
  Callout,
  Checkbox,
  Classes,
  Dialog,
  FormGroup,
  Icon,
  InputGroup,
  Intent,
  TextArea,
  Tooltip
} from '@blueprintjs/core';
import Select from 'react-select';
import { Form, Validation } from 'calidation';

// Utils
import { Settings } from '../../../utils';

// Styles
import './IssueReporterDialog.css';

// Constants
const { SAIKU_COLOR } = Settings;
const REPO_URL = 'https://gitlab.com/spiculedata/saiku4/saiku4-webframework';
const OPTIONS_TOPIC = [
  {
    value: 'bug',
    label: 'Bug Report'
  },
  {
    value: 'feature',
    label: 'Feature Request'
  }
];
const PLACEHOLDER_DESCRIPTION_BUG = `Please include:

- A clear description of the problem
- A step-by-step set of instructions to reproduce the problem (if possible)
- What results are expected
- What results you actually saw
`;
const PLACEHOLDER_DESCRIPTION_FEATURE = "Describe the feature you'd like.";
const BROWSER_INFO = `

Environment:

1. Operating system: ${browserInfo().os}
2. Browser and version: ${browserInfo().name} - ${browserInfo().fullVersion}
3. Saiku version: ${Settings.VERSION}
`;
const TOOLTIP_HELP_CONTENT = (
  <span>
    Send our support team some helpful info about your operating <br /> system
    and browser, which they'll probably have to ask for anyway.
  </span>
);

class IssueReporterDialog extends Component {
  constructor(props) {
    super(props);

    this.state = {
      initialValues: {
        topic: OPTIONS_TOPIC[0]
      },
      topicType: 'bug',
      isSystemBrowserInfo: true
    };

    this.formValidationConfig = {
      topic: {
        isRequired: 'Choose a Topic field is required'
      },
      title: {
        isRequired: 'Title field is required'
      },
      description: {
        isRequired: 'Description field is required'
      }
    };
  }

  handleSystemBrowserInfo = () => {
    this.setState(prevState => ({
      isSystemBrowserInfo: !prevState.isSystemBrowserInfo
    }));
  };

  handleSubmit = ({ fields, errors, isValid }) => {
    if (isValid) {
      const { isSystemBrowserInfo } = this.state;
      const { title, description } = fields;
      const newDescription = isSystemBrowserInfo
        ? description.concat(BROWSER_INFO)
        : description;
      const url = newGitlabIssueUrl({
        repoUrl: REPO_URL,
        title,
        description: newDescription
      });

      window.open(url, '_blank');
    }
  };

  renderInfo() {
    return (
      <Callout className="m-b-15" icon="info-sign" intent={Intent.PRIMARY}>
        NOTE: English is the universal language nowadays, so please don't
        comment using another language.
      </Callout>
    );
  }

  renderForm() {
    const { onClose } = this.props;
    const { initialValues, topicType, isSystemBrowserInfo } = this.state;

    return (
      <Form onSubmit={this.handleSubmit} style={{ margin: 0 }}>
        <Validation
          config={this.formValidationConfig}
          initialValues={initialValues}
        >
          {({ fields, errors, submitted, setField }) => (
            <Fragment>
              <div className={Classes.DIALOG_BODY}>
                {this.renderInfo()}

                <FormGroup
                  label="Choose a Topic"
                  labelFor="topic"
                  intent={
                    submitted && errors.topic ? Intent.DANGER : Intent.NONE
                  }
                  helperText={submitted && errors.topic ? errors.topic : ''}
                >
                  <Select
                    name="topic"
                    options={OPTIONS_TOPIC}
                    value={fields.topic}
                    onChange={value => {
                      this.setState({ topicType: value.value });
                      setField({ topic: value });
                    }}
                    styles={{
                      control: (styles, state) => ({
                        ...styles,
                        borderWidth: state.isFocused
                          ? '1px'
                          : submitted && errors.topic
                          ? '0px'
                          : '1px',
                        borderStyle: state.isFocused
                          ? 'solid'
                          : submitted && errors.topic
                          ? 'none'
                          : 'solid',
                        borderColor: state.isFocused
                          ? SAIKU_COLOR
                          : submitted && errors.topic
                          ? '#fff'
                          : '#ccc',
                        boxShadow: state.isFocused
                          ? `0 0 0 1px ${SAIKU_COLOR}`
                          : submitted && errors.topic
                          ? `0 0 0 0 rgba(219, 55, 55, 0),
                             0 0 0 0 rgba(219, 55, 55, 0),
                             inset 0 0 0 1px #db3737,
                             inset 0 0 0 1px rgba(16, 22, 26, 0.15),
                             inset 0 1px 1px rgba(16, 22, 26, 0.2)`
                          : null,
                        ':hover': {
                          ...styles[':hover'],
                          borderColor: state.isFocused ? SAIKU_COLOR : '#ccc'
                        }
                      }),
                      menu: (styles, state) => ({
                        ...styles,
                        zIndex: '2003'
                      }),
                      option: (styles, state) => ({
                        ...styles,
                        backgroundColor: state.isSelected ? SAIKU_COLOR : null,
                        ':hover': {
                          ...styles[':hover'],
                          backgroundColor: state.isSelected
                            ? SAIKU_COLOR
                            : '#e1ddff'
                        },
                        ':active': {
                          ...styles[':active'],
                          backgroundColor: state.isSelected ? SAIKU_COLOR : null
                        }
                      })
                    }}
                    isSearchable
                  />
                </FormGroup>
                <FormGroup
                  label="Title"
                  labelFor="title"
                  intent={
                    submitted && errors.title ? Intent.DANGER : Intent.NONE
                  }
                  helperText={submitted && errors.title ? errors.title : ''}
                >
                  <InputGroup
                    name="title"
                    intent={
                      submitted && errors.title ? Intent.DANGER : Intent.NONE
                    }
                    placeholder="Please enter a title"
                  />
                </FormGroup>
                <FormGroup
                  label="Description"
                  labelFor="description"
                  intent={
                    submitted && errors.description
                      ? Intent.DANGER
                      : Intent.NONE
                  }
                  helperText={
                    submitted && errors.description ? errors.description : ''
                  }
                >
                  <TextArea
                    name="description"
                    intent={
                      submitted && errors.description
                        ? Intent.DANGER
                        : Intent.NONE
                    }
                    rows="8"
                    placeholder={
                      topicType === 'bug'
                        ? PLACEHOLDER_DESCRIPTION_BUG
                        : PLACEHOLDER_DESCRIPTION_FEATURE
                    }
                    fill
                  />
                </FormGroup>
                <FormGroup labelFor="systemBrowserInfo">
                  <Checkbox
                    checked={isSystemBrowserInfo}
                    onChange={this.handleSystemBrowserInfo}
                  >
                    Include system and browser info{' '}
                    <Tooltip
                      className={Classes.TOOLTIP_INDICATOR}
                      content={TOOLTIP_HELP_CONTENT}
                    >
                      <Icon icon="help" iconSize={15} />
                    </Tooltip>
                  </Checkbox>
                </FormGroup>
              </div>
              <div className={Classes.DIALOG_FOOTER}>
                <div className={Classes.DIALOG_FOOTER_ACTIONS}>
                  <Button
                    type="submit"
                    text="Preview on GitLab"
                    intent={Intent.DANGER}
                  />
                  <Button text="Close" onClick={onClose} />
                </div>
              </div>
            </Fragment>
          )}
        </Validation>
      </Form>
    );
  }

  render() {
    const { onClose } = this.props;

    return (
      <Dialog
        className="sku-issue-reporter-dialog"
        title="Issue Reporter"
        icon="comment"
        canOutsideClickClose={false}
        isOpen={true}
        onClose={onClose}
      >
        {this.renderForm()}
      </Dialog>
    );
  }
}

export default IssueReporterDialog;
